(function (window) {
  /**
   * Promise构造函数
   * excutor: 内部同步执行的函数 (resolve, reject)=>{}
   */
  function Promise(excutor) {
    // 初始属性设置
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    // 保存回调函数
    this.callbacks = [];
    // 保存示例对象的this的值
    const self = this;

    // resolve函数
    function resolve(value) {
      // 判断状态，让promise对象状态只修改一次
      if (self.PromiseState !== 'pending') return;
      // 1、修改对象的状态
      self.PromiseState = 'fulfilled';
      // 2、设置对象结果值
      self.PromiseResult = value;
      // 调用回调函数
      setTimeout(() => {
        self.callbacks.forEach(element => {
          element.onResolved(value)
        });
      });

      // if (self.callback.onResolved) {
      //   self.callback.onResolved(value);
      // }
    }

    // reject函数
    function reject(reason) {
      // 判断状态，让promise对象状态只修改一次
      if (self.PromiseState !== 'pending') return;
      // 1、修改对象的状态
      self.PromiseState = 'rejected';
      // 2、设置对象结果值
      self.PromiseResult = reason;
      // 调用回调函数
      setTimeout(() => {
        self.callbacks.forEach(element => {
          element.onRejected(reason)
        });
      });

      // if (self.callback.onRejected) {
      //   self.callback.onRejected(reason);
      // }
    }
    // 同步调用执行器函数
    try {
      excutor(resolve, reject);
    } catch (error) {
      reject(error);
    }

  }

  /**
   * 为promise指定成功/失败的回调函数
   * 函数的返回值是一个新的promise对象
   */
  Promise.prototype.then = function (onResolved, onRejected) {
    if (typeof onRejected !== 'function') {
      onRejected = reason => {
        throw reason;
      }
    }
    if (typeof onResolved !== 'function') {
      onResolved = value => value;
    }
    return new Promise((resolve, reject) => {
      function handle(callback) {
        try {
          let result = callback(self.PromiseResult);
          if (result instanceof Promise) {
            result.then(
              v => {
                resolve(v);
              },
              r => {
                reject(r);
              }
            )
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      }
      // 如果当前promise还未确定了
      if (this.PromiseState === 'pending') {
        this.callbacks.push({
          onResolved(value) {
            handle(onResolved);
          },
          onRejected(reason) {
            handle(onRejected);
          }
        });
      }
      // 如果当前promise成功了
      if (this.PromiseState === 'fulfilled') {
        setTimeout(() => {
          handle(onResolved);
        });
      }
      // 如果当前promise失败了
      if (this.PromiseState === 'rejected') {
        setTimeout(() => {
          handle(onRejected);
        });
      }
    })

  }
  /**
   * 
   * @param {指定失败的回调函数} onRejected 
   */
  Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
  }

  /**
   * 指定了成功的value的promise对象
   * @param {成功的value} value 
   */
  Promise.resolve = function (value) {
    // 返回一个promise对象
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        value.then(
          v => {
            resolve(v);
          },
          r => {
            reject(r);
          }
        )
      } else {
        resolve(value);
      }
    })
  }

  /**
   * 返回指定了失败reason的promise对象
   * @param {失败的原因} reason 
   */
  Promise.reject = function (reason) {
    // 返回一个promise对象
    return new Promise((resolve, reject) => {
      reject(reason);
    })
  }

  /**
   * 返回一个promise，只有promises中所有的promise都成功时，才最终成功
   * 只要有一个失败就直接失败
   * @param {多个promise对象组成的promise数组} promises 
   * 传入的必须是promise对象数组吗？可以为一个常量。
   * 其中一个报错，就会进入catch, 其他的promise会正常执行，
   * 在创建之初（实例化）时就执行了。.then()只是拿到他的结果。
   */
  Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new Error('输入的参数必须是数组'));
      }
      //声明变量
      let count = 0;
      let arr = [];
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          v => {
            count++;
            arr[i] = v;
            if (count === promises.length) {
              resolve(arr);
            }
          },
          r => {
            reject(r);
          }
        )
      }
    })
  }

    /**
   * 返回一个promise，promises中所有的promise都执行，返回值是状态和值
   * 等待所有 Promise 完成（无论成功或失败）
   * @param {多个promise对象组成的promise数组} promises 
   * 传入的必须是promise对象数组吗？可以为一个常量。
   * 返回值里面内容是状态和value。
   */
  Promise.allSettled = function (promises) {
    return new Promise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new Error('输入的参数必须是数组'));
      }
      //声明变量
      let arr = [];
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          v => {
            count++;
            arr[i] = {
              status: 'fulfilled',
              value: v
            };
            if (arr.length === promises.length) {
              resolve(arr);
            }
          },
          r => {
            arr[i] = {
              status: 'rejected',
              value: r
            };
            if (arr.length === promises.length){
              reject(arr);
            }
          }
        )
      }
    })
  }

  /**
   * 返回一个promise, 某个promise成功或失败，则返回的promise就成功或失败
   * @param {多个promise对象组成的promise数组} promises 
   */
  Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new Error('输入的参数必须是数组'));
      }
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          v => {
            resolve(v);
          },
          r => {
            reject(r);
          }
        )
      }
    })
  };

  /**
 * 返回一个promise，只有promises中所有的promise都失败时，才最终失败
 * 只要有一个成功就直接成功
 * @param {多个promise对象组成的promise数组} promises 
 * 传入的必须是promise对象数组吗？可以为一个常量。
 * 其中一个报错，就会进入catch, 其他的promise会正常执行，
 * 在创建之初（实例化）时就执行了。.then()只是拿到他的结果。
 */
  Promise.any = function (promises) {
    return new Promise((resolve, reject) => {
      if (!Array.isArray(promises)) {
        return reject(new Error('输入的参数必须是数组'));
      }
      //声明变量
      let count = 0;
      let arr = [];
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          v => {
            resolve(arr);
          },
          r => {
            count++;
            arr[i] = r;
            if (count === promises.length) {
              reject(arr);
            }
          }
        )
      }
    })
  }


  window.Promise = Promise;

})(window)


